package ca.shojaei.mini_sat;

import java.util.*;

public class Model2Solver extends Solver{
	
	public Model getModel()
	{
		return m;
	}
	
	private Cell[][] current;
	private Cell[][] next;
	State currentState, nextState;
	
	public Model2Solver(Vector<int[]> init){
		
	
		//ArrayList<State2> states = new ArrayList<State2>();
		 current = new Cell[5][5];
		 next = new Cell[5][5];
		 
		 initConfig(current);
		 initConfig(next);
		 
		 //Initialaize current
		 
		 for(int i = 0; i < init.size(); i++){
				current[init.get(i)[0]][init.get(i)[1]].setAlive(true);
		 }
		 
		 currentState = new State(getVars(current), 1);
		 
		 boolean flagFirst = true;
		 
		 for(int i = 2; i < 10002; i++ )
		 {
			 
			 next = getNextState();
			 
			 nextState = new State(getVars(next), i);
			 
			 currentState.addNextState(nextState);
			 if(flagFirst){
				 
				 m = new Model(currentState);
				 flagFirst = false;
			 }
				 
			 
			 m.addState(currentState);
			 
			 currentState = nextState;
			 current = next;
			 
		 }
		 		 
	}
	
	
    private Cell[][] getNextState(){
		
		Cell[][] newStates =  new Cell[5][5];
		initConfig(newStates);
		for(int i = 0; i <5; i++){
			for (int j = 0; j<5; j++){
					newStates[i][j].setAlive(!cellDies(i,j));
			}
		}
		
		return newStates;
	}
	
	
	private HashMap<String, Integer> getVars(Cell[][] cell)
	{
		 HashMap<String, Integer> result = new HashMap<String,Integer>();
		
		 int counter = 1;
		 
		 for(int i = 0; i < 5; i++)
		 {
			 for(int j = 0; j < 5 ; j++){
				 
				 result.put(String.valueOf(cell[i][j].getVar()), getCounter(cell[i][j].isAlive(), counter) );
				 counter++;
			 }
			 
		 }
		 
		 return result;
	}
	
	
	private int getCounter(boolean b, int counter)
	{
		if(!b)
			return -1 * counter;
		else
			return counter;
				
	}
	private void initConfig(Cell[][] conf)
	{
         Cell state;
		
		char ch = 'a';
		
		for(int i = 0; i <5; i++){
			for (int j = 0; j<5; j++){
				
				state = new Cell(getNeighbors(i,j), ch);
				conf[i][j] = state;
				ch = (char)(ch +1);
			}
		}
	}
	
	
	private ArrayList<int[]> getNeighbors(int row, int col){
		
		ArrayList<int[]> neighbors = new ArrayList<int[]>();
		
		int[] n = new int[2];
		
		//top left
		n[0] = boundNumber(row,-1);
		n[1] = boundNumber(col,-1);
		neighbors.add(n);
		
		//top 
		n = new int[2];
		n[0] = boundNumber(row,-1);
		n[1] = col;
		neighbors.add(n);
		
		//top right
		n = new int[2];
		n[0] = boundNumber(row,-1);
		n[1] = boundNumber(col,1);
		neighbors.add(n);
		
		//right
		n = new int[2];
		n[0] = row;
		n[1] = boundNumber(col,1);
		neighbors.add(n);
		
		//bottom right
		n = new int[2];
		n[0] = boundNumber(row,1);
		n[1] = boundNumber(col,1);
		neighbors.add(n);
		
		//bottom
		n = new int[2];
		n[0] = boundNumber(row,1);
		n[1] = col;
		neighbors.add(n);
		
		//bottom left
		n = new int[2];
		n[0] = boundNumber(row,1);
		n[1] = boundNumber(col,-1);
		neighbors.add(n);
		
		//left
		n = new int[2];
		n[0] = row;
		n[1] = boundNumber(col,-1);
		neighbors.add(n);
		
		return neighbors;
		
	}
	
	
    private boolean cellDies(int row, int col){
		
		ArrayList<int[]> neighbors = current[row][col].getNeighbors();
		int deadN = 0;
		int liveN = 0;
		int [] n;
		
		for(int i = 0; i < 8; i++){
			n = neighbors.get(i);
			if((current[n[0]][n[1]]).isAlive())
				liveN++;
			else
				deadN++;
		}
		
		return (liveN < 2 || liveN > 3)? true : false;
	}
	
	
    private int boundNumber(int i, int j){
		
		int r = i + j;
		if(r < 0)
			r = 4;
		if(r > 4)
			r = 1;
		return r;
	}

}
